/*******************************************************************************
 * Copyright (c) 2007 University of Oslo.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     University of Oslo - initial API and implementation
 *******************************************************************************/

package com.cea.papyrus.diagram.sequence.sedi.edit.handlers;


import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.RequestConstants;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.uml2.uml.InteractionOperand;

import com.cea.papyrus.core.utils.LookForElement;
import com.cea.papyrus.diagram.sequence.sedi.edit.command.AnalyseOwnerCommand;
import com.cea.papyrus.diagram.sequence.sedi.model.util.ModelUtil;
import com.cea.papyrus.diagraminterchange2.di2.Diagram;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;

/**
 * This handler is installed on interaction frames to handle dragging of interaction
 * operand guards. It is required because CF figures are "transparent" and do not receive
 * the guard movement requests directly.
 * 
 * @author frankd@ifi.uio.no
 * @see InteractionAddCFHandler
 */
public class InteractionAddGuardHandler {

    public final EditPolicy hostPolicy;

    public InteractionAddGuardHandler(final EditPolicy hostPolicy) {
        this.hostPolicy = hostPolicy;
    }

    @SuppressWarnings("unchecked")
    public Command[] getAddCommands(final GraphNode interactionView, GraphicalEditPart guardEP,
            Rectangle r) {
        // 'r' is in absolute coords
        // We don't add the guard as a child of the interaction frame, but
        // rather move it so that it appears to be inside.

        GraphNode guardView = (GraphNode) guardEP.getModel();

        Diagram diagram = LookForElement.getDiagram(guardView);

        // Find the CF that will receive the guard
        AnalyseOwnerCommand ownerCmd = new AnalyseOwnerCommand();
        ownerCmd.setAnyEditPart(guardEP);
        ownerCmd.setDiagram(diagram);
        ownerCmd.setLocation(r.getLocation());
        ownerCmd.execute();
        if (!(ownerCmd.getOwner() instanceof InteractionOperand))
            return null; // Only allowed inside operands

        InteractionOperand targetOperand = (InteractionOperand) ownerCmd.getOwner();

        GraphNode cfView = ModelUtil.getGraphNode(targetOperand.getOwner(), diagram);
        GraphicalEditPart cfEP =
                (GraphicalEditPart) guardEP.getViewer().getEditPartRegistry().get(cfView);
        Rectangle currentBounds = new Rectangle(guardView.getPosition(), guardView.getSize());

        cfEP.getFigure().translateToRelative(r);
        cfEP.getFigure().translateFromParent(r);

        // Construct a move request and direct it to the diagram editpart
        ChangeBoundsRequest req = new ChangeBoundsRequest();
        req.setType(RequestConstants.REQ_MOVE_CHILDREN);
        req.setEditParts(guardEP);
        req.setLocation(r.getLocation());
        req.setMoveDelta(new Point(r.x - currentBounds.x, r.y - currentBounds.y));

        return new Command[] {
            cfEP.getCommand(req)
        };
    }
}
